package rpg.core
{
	import rpg.Utils.AStar;
	import rpg.Utils.GameUtils;
	import rpg.Utils.Log;
	import rpg.Utils.Val;
	import rpg.data.FightState;
	import rpg.data.Spell;
	import rpg.data.SpellAnimation;
	import rpg.factory.GameFactory;
	import rpg.interfaces.IUpdate;
	import rpg.manager.DataManager;
	import rpg.manager.GameManager;
	import rpg.role.Hero;
	import rpg.role.SceneObject;
	import rpg.update.Update;

	public class AutoCastSpellComponent extends FrameComponent
	{
		public var role : Hero;
		private var cdComponent : CDComponent
		/**
		 * 当前攻击目标
		 */
		public var attackTarget : Hero;
		/**
		 * 自动释放技能
		 */
		public var autoCastSpell : Spell;
		/**
		 * 当前使用技能
		 */
		public var currCastSpell : Spell;
		public var castDelayTime : int;
		public var castElapsedTime : int;

		private var targetX : int;
		private var targetY : int;


		private var gameFactory : GameFactory;
		private var gm : GameManager;

		public function AutoCastSpellComponent(type : * = null)
		{
			super(type == null ? AutoCastSpellComponent : type);
		}

		override public function notifyAdded() : void
		{
			role = owner as Hero;
			gameFactory = GameFactory.getInstance();
			gm = GameManager.getInstance();
			this.frameRate = 10;
		}

		override public function update(delay : uint) : void
		{
			if(!attackTarget)
				return;
			if(!attackTarget.isActive)
			{
				attackTarget = null;
				return;
			}
			if(currCastSpell == null)
				currCastSpell = autoCastSpell;
			castSpell(currCastSpell);
		}

		/**
		 * 释放技能
		 * @param spell
		 *
		 */
		public function castSpell(spell : Spell) : void
		{
			if(role.isDead || !role.canAttack || !spell)
			{
				return;
			}
			cdComponent = role.getComponent(CDComponent);
			if(cdComponent == null)
			{
				cdComponent = new CDComponent();
				role.addComponent(cdComponent);
			}
			if(!cdComponent.isCD(spell.id))
			{
				currCastSpell = spell;
				//释放给自己的BUFF
				if(isReleaseAtSelf(currCastSpell))
				{
					castMySelfSpellAnimation();
				}
				//释放在自己身边
				else if(isReleaseAtSelfGround(currCastSpell))
				{
					castSelfGroundSpell();
				}
				else
				{
					if(attackTarget == null)
					{
						if(gm.selectTarget && gm.selectTarget != role)
							attackTarget = gm.selectTarget as Hero;
						else
							attackTarget = gm.getNearestEnemy(role);
					}
					triggerNextAttack();
				}
			}
		}

		/**
		 * 检测攻击
		 * @param target
		 * @param spell
		 *
		 */
		public function attack(target : Hero) : void
		{
			if(!target || target.isDead || role == target)
			{
				return;
			}
			attackTarget = target;
			if(role == gm.selfRole)
				gm.targetSelect(target);
			castSpell(autoCastSpell);
		}

		/**
		 * 停止攻击
		 *
		 */
		public function stopAttack() : void
		{
			attackTarget = null;
			currCastSpell = null;
		}

		/**
		 *  以自己为中心点释放技能
		 *
		 */
		public function castSelfGroundSpell() : void
		{
			var attackDst : int = Math.sqrt(Math.pow(currCastSpell.xExtHurtRange * .5 * GameUtils.GRID_WIDTH , 2) + Math.pow(currCastSpell.yExtHurtRange * .5 * GameUtils.GRID_HEIGHT , 2));
			//以自己为中心点释放技能
			var enemyArray : Array = gm.getNearestEnemysByDst(role , attackDst);
			addTargetsAnimation(enemyArray);
			addTargetsBuff(enemyArray);
			addTargetsDamageState(enemyArray);
			castMySelfSpellAnimation();
		}

		/**
		 * 攻击单体目标
		 *
		 */
		public function castTargetSpell(target : Hero) : void
		{
			//飞行技能
			if(hasFlyEffect(currCastSpell))
			{
				var flyAnimation : SpellAnimation = currCastSpell.getFlySpellAnimation();
				gameFactory.createFollowFlyAnimation(flyAnimation.animationIndex + "" , currCastSpell.flightSpeed / 1000 , role.mapX , role.mapY - role.height * (flyAnimation.animationPosition / 100) , target , flyAnimation.needRotate , flyAnimation.animationSpeed , 0);
				gameFactory.createFollowFlyAnimation(flyAnimation.animationIndex + "" , currCastSpell.flightSpeed / 1000 , role.mapX , role.mapY - role.height * (flyAnimation.animationPosition / 100) , target , flyAnimation.needRotate , flyAnimation.animationSpeed , 90);
			}
			//冲锋技能
			else if(isRushSpell(currCastSpell))
			{
				var rushComponent : RushComponent = new RushComponent();
				var dst : int = GameUtils.getDistance(role.mapX , role.mapY , target.mapX , target.mapY);
				rushComponent.setTargetPosition(target.mapX , target.mapY);
				rushComponent.speed = dst / 1000;
				role.addComponent(rushComponent);
			}
			//闪烁技能
			else if(isBlinkSpell(currCastSpell))
			{
				var blinkComponent : BlinkComponent = new BlinkComponent();
				blinkComponent.setTargetPosition(target.mapX , target.mapY);
				blinkComponent.setDration(500);
				role.addComponent(blinkComponent);
			}
			addTargetsAnimation([target]);
			addTargetsBuff([target]);
			addTargetsDamageState([target]);
		}


		/**
		 * 给人物添加一个BUFF
		 * @param target
		 * @param id
		 *
		 */
		protected function addStateBuff(target : Hero , id : int) : void
		{
			if(id <= 0)
				return;
			var fightState : FightState = DataManager.getInstance().globalbuffer[id];
			var bufferComponent : BufferComponent = target.getComponent(fightState.id) as BufferComponent;
			if(bufferComponent == null)
			{
				bufferComponent = new BufferComponent(fightState.id);
				target.addComponent(bufferComponent);
			}
			if(fightState.animation)
			{
				createAnimation(target , fightState.getAnimation());
					//gameFactory.createTargetAnimation(target , fightState.animation , Val.BOTTOM);
			}
			bufferComponent.setState(fightState);
			bufferComponent.setDration(fightState.frameTime * fightState.totalFrames);
			bufferComponent.frameDelay = fightState.frameTime;
			bufferComponent.totalFrames = fightState.totalFrames;
		}

		/**
		 * 给所有目标添加一个伤害值
		 * @param targetArray
		 *
		 */
		protected function addTargetsDamageState(targetArray : Array) : void
		{
			for each(var tmpTarget : Hero in targetArray)
			{
				tmpTarget.data.currHP -= 20;
			}
		}

		/**
		 * 给所有目标添加一个状态
		 * @param targetArray
		 *
		 */
		protected function addTargetsBuff(targetArray : Array) : void
		{
			var tmpTarget : Hero;
			for each(tmpTarget in targetArray)
			{
				addStateBuff(tmpTarget , currCastSpell.targetStates);
			}
			if(currCastSpell.beatBackDistance > 0)
			{
				for each(tmpTarget in targetArray)
				{
					var rotation : int = GameUtils.getRotation(tmpTarget.mapX , tmpTarget.mapY , role.mapX , role.mapY);
					tmpTarget.dir = GameUtils.getDirection(rotation);
					var beatBackComponent : BeatBackComponent = tmpTarget.getComponent(BeatBackComponent);
					if(beatBackComponent == null)
					{
						beatBackComponent = new BeatBackComponent();
						tmpTarget.addComponent(beatBackComponent);
					}
					var reverseDir : int = GameUtils.getReverseDirByDir(tmpTarget.dir);
					var reverseRotation : int = GameUtils.getRotationByDir(reverseDir);
					var beatBackDst : int = currCastSpell.beatBackDistance * GameUtils.GRID_HEIGHT;
					var beatBackX : int = tmpTarget.mapX + GameUtils.cosD(reverseRotation) * beatBackDst;
					var beatBackY : int = tmpTarget.mapY + GameUtils.sinD(reverseRotation) * beatBackDst;
					beatBackComponent.setTargetPosition(beatBackX , beatBackY);
					beatBackComponent.speed += beatBackDst / 1000;
				}
			}
		}

		/**
		 * 添加玩家自己使用技能的特效
		 *
		 */
		protected function addSelfAnimation() : void
		{
			var spellAnimation : SpellAnimation = currCastSpell.getSelfSpellAnimation();
			createAnimation(role , spellAnimation);
		}

		/**
		 * 添加释放的目标身上的技能特效
		 *
		 */
		protected function addTargetsAnimation(targetArray : Array) : void
		{
			var spellAnimation : SpellAnimation = currCastSpell.getTargetSpellAnimation();
			for each(var tmpTarget : Hero in targetArray)
			{
				createAnimation(tmpTarget , spellAnimation);
			}
		}

		/**
		 * 添加技能自己本身的特效
		 *
		 */
		protected function addAnimation() : void
		{
			var spellAnimation : SpellAnimation = currCastSpell.getAnimationSpellAnimation();
			createAnimation(role , spellAnimation);
		}

		/**
		 * 添加一个技能动画
		 * @param target
		 * @param spellAnimation
		 *
		 */
		protected function createAnimation(target : SceneObject , spellAnimation : SpellAnimation) : void
		{
			if(spellAnimation == null)
				return;
			if(spellAnimation.animationType == 0)
			{
				createTargetAnimation(target , spellAnimation);
			}
			else
			{
				createSceneAnimation(target , spellAnimation);
			}
		}


		/**
		 * 在目标添加一个动画
		 * @param target
		 * @param spellAnimation
		 *
		 */
		protected function createTargetAnimation(target : SceneObject , spellAnimation : SpellAnimation) : void
		{
			var offsetY : int = target.height * (spellAnimation.animationPosition / 100);
			var rotation : int = 0;
			if(spellAnimation.needRotate)
				rotation = GameUtils.getRotation(role.mapX , target.mapY , target.mapX , target.mapY);
			gameFactory.createTargetAnimation(target , spellAnimation.animationIndex + "" , spellAnimation.zIndex , spellAnimation.animationSpeed , spellAnimation.animationDelay , spellAnimation.animationLoops , rotation , 0 , offsetY)
		}

		/**
		 * 在场景添加一个动画
		 * @param target
		 * @param spellAnimation
		 *
		 */
		protected function createSceneAnimation(target : SceneObject , spellAnimation : SpellAnimation) : void
		{
			var offsetY : int = target.height * (spellAnimation.animationPosition / 100);
			var rotation : int = 0;
			if(spellAnimation.needRotate)
				rotation = GameUtils.getRotation(role.mapX , role.mapY , target.mapX , target.mapY);
			gameFactory.createSceneAnimation(target , spellAnimation.animationIndex + "" , spellAnimation.zIndex , spellAnimation.animationSpeed , spellAnimation.animationDelay , spellAnimation.animationLoops , rotation , 0 , offsetY)
		}

		/**
		 * 触发下一次攻击
		 */
		protected function triggerNextAttack() : void
		{
			if(!checkCanAttack(attackTarget))
			{
				return;
			}
			if(isInRange(currCastSpell , attackTarget.mapX , attackTarget.mapY))
			{
				var rotation : int = GameUtils.getRotation(role.mapX , role.mapY , attackTarget.mapX , attackTarget.mapY);
				role.dir = GameUtils.getDirection(rotation);
				//单体目标技能
				if(isReleaseAtTarget(currCastSpell))
				{
					castTargetSpell(attackTarget);
				}
				//范围攻击
				else if(isReleaseAtGround(currCastSpell))
				{
					Log.print("暂不开放");
					return;
				}
				castMySelfSpellAnimation();
			}
			else
			{
				var position : Array = getAtackPosition(currCastSpell.releaseRange , attackTarget.mapX , attackTarget.mapY);
				role.stateComponent.walkFinishFun(position[0] , position[1] , triggerNextAttack);
			}
		}

		protected function castMySelfSpellAnimation() : void
		{
			addSelfAnimation();
			addAnimation();
			addStateBuff(role , currCastSpell.selfStates);
			role.changeState(Val.ATTACK);
			role.avatarComponent.duration = currCastSpell.actionSpeed;

			//添加硬直
			if(currCastSpell.hardTime > 0)
			{
				var roleHardComponent : RoleHardComponent = role.getComponent(RoleHardComponent);
				if(roleHardComponent == null)
				{
					roleHardComponent = new RoleHardComponent();
					role.addComponent(roleHardComponent);
				}
				roleHardComponent.setDration(currCastSpell.hardTime);
			}
			cdComponent.createCD(currCastSpell);
			currCastSpell = null;
		}

		/**
		 * 检测是否可以攻击
		 * @return
		 *
		 */
		protected function checkCanAttack(target : Hero) : Boolean
		{
			if(target == null || role == null || currCastSpell == null)
				return false;
			if(target.isDead || role.isDead)
				return false;
			if(role == target)
				return false;
			if(!role.canAttack)
				return false;
			return true;
		}

		/**
		 *
		 * 是否在可攻击范围内
		 * @param spell
		 * @param targetGridX
		 * @param targetGridY
		 * @return
		 *
		 */
		protected function isInRange(spell : Spell , targetX : int , targetY : int) : Boolean
		{
			var selfGridX : int = GameUtils.getGridXByPixel(role.mapX);
			var selfGridY : int = GameUtils.getGridYByPixel(role.mapY);
			var dx : int = GameUtils.getGridXByPixel(targetX) - selfGridX;
			var dy : int = GameUtils.getGridYByPixel(targetY) - selfGridY;
			var gridDist : int = (dx * dx + dy * dy);
			if(gridDist == 0)
				return true;
			return gridDist <= (spell.releaseRange * spell.releaseRange);
		}

		/**
		 * 获得攻击敌人的地图坐标
		 * @param releaseRange
		 * @param targetX
		 * @param targetY
		 * @return
		 *
		 */
		protected function getAtackPosition(releaseRange : int , targetX : int , targetY : int) : Array
		{
			if(releaseRange <= 0)
				return [targetX , targetY];
			//攻击距离
			var range : int = releaseRange * GameUtils.GRID_WIDTH;
			//角度
			var angle : int = GameUtils.getRotation(role.mapX , role.mapY , targetX , targetY);
			var dx : int = GameUtils.cosD(angle) * range;
			var dy : int = GameUtils.sinD(angle) * range;
			//可攻击的最近x,y距离
			var position : Array = [targetX - dx , targetY - dy];
			//2点之间的距离
			var dist : int = GameUtils.getDistance(role.mapX , role.mapY , position[0] , position[1]);
			var gridX : int = GameUtils.getGridXByPixel(position[0]);
			var gridY : int = GameUtils.getGridYByPixel(position[1]);
			if(AStar.getInstance().isBlock(gridX , gridY) || dist < GameUtils.GRID_WIDTH)
			{
				position = getAtackPosition(releaseRange - 1 , targetX , targetY);
			}
			return position;
		}


		/**
		 * 是否释放给自己的技能
		 * @param spell
		 * @return
		 *
		 */
		public function isReleaseAtSelf(spell : Spell) : Boolean
		{
			var value : Boolean = spell.releaseRange == 0 && isReleaseAtTarget(spell);
			return value;
		}

		/**
		 * 释放在自己身边
		 * @param spell
		 * @return
		 *
		 */
		public function isReleaseAtSelfGround(spell : Spell) : Boolean
		{
			var value : Boolean = spell.releaseRange == 0 && isReleaseAtGround(spell);
			return value;
		}

		/**
		 * 是否释放在空地的技能
		 * @param spell
		 * @return
		 *
		 */
		public function isReleaseAtGround(spell : Spell) : Boolean
		{
			return spell.xExtHurtRange > 0;
		}

		/**
		 * 是否释放在敌人身上的技能
		 * @param spell
		 * @return
		 *
		 */
		public function isReleaseAtTarget(spell : Spell) : Boolean
		{
			return spell.xExtHurtRange == 0;
		}

		/**
		 * 是否闪烁技能
		 * @param spell
		 * @return
		 *
		 */
		public function isBlinkSpell(spell : Spell) : Boolean
		{
			return spell.isDamage && (spell).isBlink;
		}

		/**
		 * 是否有飞行技能
		 * @param spell
		 * @return
		 *
		 */
		protected function hasFlyEffect(spell : Spell) : Boolean
		{
			var flyerSpellAnimation : SpellAnimation = spell.getFlySpellAnimation();
			return flyerSpellAnimation && flyerSpellAnimation.animationIndex > 0;
		}

		/**
		 * 是否冲锋技能
		 * @param spell
		 * @return
		 *
		 */
		public function isRushSpell(spell : Spell) : Boolean
		{
			if(spell.isDamage && spell.isRushSpell)
			{
				return true;
			}
			return false;
		}
	}
}